#include "Script_Warlock.h"

#include "Groups/Group.h"

#ifndef WARLOCK_CLOSER_DISTANCE
# define WARLOCK_CLOSER_DISTANCE 25
#endif

#ifndef WARLOCK_RANGE_DISTANCE
# define WARLOCK_RANGE_DISTANCE 30
#endif

Script_Warlock::Script_Warlock(RobotAI* pmSourceAI) :Script_Base(pmSourceAI)
{

}

bool Script_Warlock::HealMe()
{
	return false;
}

bool Script_Warlock::Tank(Unit* pmTarget)
{
	return false;
}

bool Script_Warlock::Healer(Unit* pmTarget)
{
	return false;
}

bool Script_Warlock::DPS(Unit* pmTarget)
{
	switch (sourceAI->characterTalentTab)
	{
	case 0:
	{
		return DPS_Affliction(pmTarget);
	}
	case 1:
	{
		return DPS_Demonology(pmTarget);
	}
	case 2:
	{
		return DPS_Destruction(pmTarget);
	}
	default:
		return DPS_Common(pmTarget);
	}
}

bool Script_Warlock::DPS_Affliction(Unit* pmTarget)
{
	Player* me = ObjectAccessor::FindPlayer(sourceAI->characterGUID);
	if (!me)
	{
		return false;
	}
	if (!pmTarget)
	{
		return false;
	}
	else if (!me->CanAttack(pmTarget))
	{
		return false;
	}
	else if (!pmTarget->isAlive())
	{
		return false;
	}
	float targetDistance = me->GetDistance(pmTarget);
	if (targetDistance > 200)
	{
		return false;
	}
	sourceAI->BaseMove(pmTarget, WARLOCK_CLOSER_DISTANCE, false);
	if ((me->GetPower(Powers::POWER_MANA) * 100 / me->GetMaxPower(Powers::POWER_MANA)) < 10)
	{
		if (!me->GetCurrentSpell(CURRENT_AUTOREPEAT_SPELL))
		{
			if (sourceAI->CastSpell(pmTarget, "Shoot", WARLOCK_RANGE_DISTANCE))
			{
				return true;
			}
		}
	}
	if (sourceAI->CastSpell(pmTarget, "Shadow Bolt", WARLOCK_RANGE_DISTANCE))
	{
		return true;
	}

	return true;
}

bool Script_Warlock::DPS_Demonology(Unit* pmTarget)
{
	Player* me = ObjectAccessor::FindPlayer(sourceAI->characterGUID);
	if (!me)
	{
		return false;
	}
	if (!pmTarget)
	{
		return false;
	}
	else if (!me->CanAttack(pmTarget))
	{
		return false;
	}
	else if (!pmTarget->isAlive())
	{
		return false;
	}
	float targetDistance = me->GetDistance(pmTarget);
	if (targetDistance > 200)
	{
		return false;
	}
	sourceAI->BaseMove(pmTarget, WARLOCK_CLOSER_DISTANCE, false);
	if ((me->GetPower(Powers::POWER_MANA) * 100 / me->GetMaxPower(Powers::POWER_MANA)) < 10)
	{
		if (!me->GetCurrentSpell(CURRENT_AUTOREPEAT_SPELL))
		{
			if (sourceAI->CastSpell(pmTarget, "Shoot", WARLOCK_RANGE_DISTANCE))
			{
				return true;
			}
		}
	}
	if (sourceAI->CastSpell(pmTarget, "Shadow Bolt", WARLOCK_RANGE_DISTANCE))
	{
		return true;
	}

	return true;
}

bool Script_Warlock::DPS_Destruction(Unit* pmTarget)
{
	Player* me = ObjectAccessor::FindPlayer(sourceAI->characterGUID);
	if (!me)
	{
		return false;
	}
	if (!pmTarget)
	{
		return false;
	}
	else if (!me->CanAttack(pmTarget))
	{
		return false;
	}
	else if (!pmTarget->isAlive())
	{
		return false;
	}
	float targetDistance = me->GetDistance(pmTarget);
	if (targetDistance > 200)
	{
		return false;
	}
	sourceAI->BaseMove(pmTarget, WARLOCK_CLOSER_DISTANCE, false);
	if ((me->GetPower(Powers::POWER_MANA) * 100 / me->GetMaxPower(Powers::POWER_MANA)) < 10)
	{
		if (!me->GetCurrentSpell(CURRENT_AUTOREPEAT_SPELL))
		{
			if (sourceAI->CastSpell(pmTarget, "Shoot", WARLOCK_RANGE_DISTANCE))
			{
				return true;
			}
		}
	}

	Group* myGroup = me->GetGroup();
	if (myGroup)
	{
		for (GroupReference* groupRef = myGroup->GetFirstMember(); groupRef != nullptr; groupRef = groupRef->next())
		{
			Player* member = groupRef->getSource();
			if (sRobotManager->playerGroupRoleCache[member->GetGUIDLow()] == 1)
			{
				if (member->getAttackers().size() >= 3)
				{
					uint32 inRangeCount = 0;
					for (std::set<Unit*>::const_iterator i = member->getAttackers().begin(); i != member->getAttackers().end(); ++i)
					{
						if ((*i)->GetDistance(member) < AOE_TARGETS_RANGE)
						{
							inRangeCount++;
							if (inRangeCount >= 3)
							{
								if (sourceAI->CastSpell((*i), "Shadowfury", WARLOCK_RANGE_DISTANCE))
								{
									return true;
								}
								if (sourceAI->CastSpell((*i), "Rain of Fire", WARLOCK_RANGE_DISTANCE))
								{
									return true;
								}
							}
						}
					}
				}
			}
		}
	}

	if (sourceAI->CastSpell(pmTarget, "Immolate", WARLOCK_RANGE_DISTANCE, true, true))
	{
		return true;
	}
	if (sourceAI->CastSpell(pmTarget, "Conflagrate", WARLOCK_RANGE_DISTANCE))
	{
		return true;
	}
	if (sourceAI->CastSpell(pmTarget, "Chaos Bolt", WARLOCK_RANGE_DISTANCE))
	{
		return true;
	}
	if (sourceAI->CastSpell(pmTarget, "Incinerate", WARLOCK_RANGE_DISTANCE))
	{
		return true;
	}

	if (sourceAI->CastSpell(pmTarget, "Shadow Bolt", WARLOCK_RANGE_DISTANCE))
	{
		return true;
	}

	return true;
}

bool Script_Warlock::DPS_Common(Unit* pmTarget)
{
	Player* me = ObjectAccessor::FindPlayer(sourceAI->characterGUID);
	if (!me)
	{
		return false;
	}
	if (!pmTarget)
	{
		return false;
	}
	else if (!me->CanAttack(pmTarget))
	{
		return false;
	}
	else if (!pmTarget->isAlive())
	{
		return false;
	}
	float targetDistance = me->GetDistance(pmTarget);
	if (targetDistance > 200)
	{
		return false;
	}
	sourceAI->BaseMove(pmTarget, WARLOCK_CLOSER_DISTANCE, false);
	if ((me->GetPower(Powers::POWER_MANA) * 100 / me->GetMaxPower(Powers::POWER_MANA)) < 10)
	{
		if (!me->GetCurrentSpell(CURRENT_AUTOREPEAT_SPELL))
		{
			if (sourceAI->CastSpell(pmTarget, "Shoot", WARLOCK_RANGE_DISTANCE))
			{
				return true;
			}
		}
	}
	if (sourceAI->CastSpell(pmTarget, "Shadow Bolt", WARLOCK_RANGE_DISTANCE))
	{
		return true;
	}

	return true;
}

bool Script_Warlock::Attack(Unit* pmTarget)
{
	switch (sourceAI->characterTalentTab)
	{
	case 0:
	{
		return Attack_Affliction(pmTarget);
	}
	case 1:
	{
		return Attack_Demonology(pmTarget);
	}
	case 2:
	{
		return Attack_Destruction(pmTarget);
	}
	default:
		return Attack_Common(pmTarget);
	}
}

bool Script_Warlock::Attack_Affliction(Unit* pmTarget)
{
	Player* me = ObjectAccessor::FindPlayer(sourceAI->characterGUID);
	if (!me)
	{
		return false;
	}
	if (!pmTarget)
	{
		return false;
	}
	else if (!me->CanAttack(pmTarget))
	{
		return false;
	}
	else if (!pmTarget->isAlive())
	{
		return false;
	}
	float targetDistance = me->GetDistance(pmTarget);
	if (targetDistance > 200)
	{
		return false;
	}
	sourceAI->BaseMove(pmTarget, WARLOCK_CLOSER_DISTANCE, false);
	if ((me->GetPower(Powers::POWER_MANA) * 100 / me->GetMaxPower(Powers::POWER_MANA)) < 10)
	{
		if (!me->GetCurrentSpell(CURRENT_AUTOREPEAT_SPELL))
		{
			if (sourceAI->CastSpell(pmTarget, "Shoot", WARLOCK_RANGE_DISTANCE))
			{
				return true;
			}
		}
	}
	if (sourceAI->CastSpell(pmTarget, "Shadow Bolt", WARLOCK_RANGE_DISTANCE))
	{
		return true;
	}

	return true;
}

bool Script_Warlock::Attack_Demonology(Unit* pmTarget)
{
	Player* me = ObjectAccessor::FindPlayer(sourceAI->characterGUID);
	if (!me)
	{
		return false;
	}
	if (!pmTarget)
	{
		return false;
	}
	else if (!me->CanAttack(pmTarget))
	{
		return false;
	}
	else if (!pmTarget->isAlive())
	{
		return false;
	}
	float targetDistance = me->GetDistance(pmTarget);
	if (targetDistance > 200)
	{
		return false;
	}
	sourceAI->BaseMove(pmTarget, WARLOCK_CLOSER_DISTANCE, false);
	if ((me->GetPower(Powers::POWER_MANA) * 100 / me->GetMaxPower(Powers::POWER_MANA)) < 10)
	{
		if (!me->GetCurrentSpell(CURRENT_AUTOREPEAT_SPELL))
		{
			if (sourceAI->CastSpell(pmTarget, "Shoot", WARLOCK_RANGE_DISTANCE))
			{
				return true;
			}
		}
	}
	if (sourceAI->CastSpell(pmTarget, "Shadow Bolt", WARLOCK_RANGE_DISTANCE))
	{
		return true;
	}

	return true;
}

bool Script_Warlock::Attack_Destruction(Unit* pmTarget)
{
	Player* me = ObjectAccessor::FindPlayer(sourceAI->characterGUID);
	if (!me)
	{
		return false;
	}
	if (!pmTarget)
	{
		return false;
	}
	else if (!me->CanAttack(pmTarget))
	{
		return false;
	}
	else if (!pmTarget->isAlive())
	{
		return false;
	}
	float targetDistance = me->GetDistance(pmTarget);
	if (targetDistance > 200)
	{
		return false;
	}
	sourceAI->BaseMove(pmTarget, WARLOCK_CLOSER_DISTANCE, false);
	if ((me->GetPower(Powers::POWER_MANA) * 100 / me->GetMaxPower(Powers::POWER_MANA)) < 10)
	{
		if (!me->GetCurrentSpell(CURRENT_AUTOREPEAT_SPELL))
		{
			if (sourceAI->CastSpell(pmTarget, "Shoot", WARLOCK_RANGE_DISTANCE))
			{
				return true;
			}
		}
	}
	if (sourceAI->CastSpell(pmTarget, "Immolate", WARLOCK_RANGE_DISTANCE, true, true))
	{
		return true;
	}
	if (sourceAI->CastSpell(pmTarget, "Conflagrate", WARLOCK_RANGE_DISTANCE))
	{
		return true;
	}
	if (sourceAI->CastSpell(pmTarget, "Chaos Bolt", WARLOCK_RANGE_DISTANCE))
	{
		return true;
	}
	if (sourceAI->CastSpell(pmTarget, "Incinerate", WARLOCK_RANGE_DISTANCE))
	{
		return true;
	}

	if (sourceAI->CastSpell(pmTarget, "Shadow Bolt", WARLOCK_RANGE_DISTANCE))
	{
		return true;
	}

	return true;
}

bool Script_Warlock::Attack_Common(Unit* pmTarget)
{
	Player* me = ObjectAccessor::FindPlayer(sourceAI->characterGUID);
	if (!me)
	{
		return false;
	}
	if (!pmTarget)
	{
		return false;
	}
	else if (!me->CanAttack(pmTarget))
	{
		return false;
	}
	else if (!pmTarget->isAlive())
	{
		return false;
	}
	float targetDistance = me->GetDistance(pmTarget);
	if (targetDistance > 200)
	{
		return false;
	}
	sourceAI->BaseMove(pmTarget, WARLOCK_CLOSER_DISTANCE, false);
	if ((me->GetPower(Powers::POWER_MANA) * 100 / me->GetMaxPower(Powers::POWER_MANA)) < 10)
	{
		if (!me->GetCurrentSpell(CURRENT_AUTOREPEAT_SPELL))
		{
			if (sourceAI->CastSpell(pmTarget, "Shoot", WARLOCK_RANGE_DISTANCE))
			{
				return true;
			}
		}
	}
	if (sourceAI->CastSpell(pmTarget, "Shadow Bolt", WARLOCK_RANGE_DISTANCE))
	{
		return true;
	}

	return true;
}

bool Script_Warlock::Buff(Unit* pmTarget)
{
	Player* me = ObjectAccessor::FindPlayer(sourceAI->characterGUID);
	if (!me)
	{
		return false;
	}
	Pet* myPet = me->GetPet();
	if (!myPet)
	{
		if (sourceAI->CastSpell(me, "Summon Imp"))
		{
			return true;
		}
	}	

	return false;
}
